package com.cheer.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.ActivityDao;
import com.cheer.entity.ActivityEntity;
import com.cheer.entity.OaLearnClassEntity;
import com.cheer.entity.OaUserEntity;
import com.cheer.enums.ActivityStatusEnum;
import com.cheer.enums.ActivityTypeEnum;
import com.cheer.enums.IsPublishTypeEnum;
import com.cheer.enums.OaIntegralRuleEnum;
import com.cheer.exception.ServiceException;
import com.cheer.param.ActivityCheckinParam;
import com.cheer.service.*;
import com.cheer.utils.BeanUtil;
import com.cheer.vo.ActivityInfoVO;
import com.cheer.vo.ActivityPageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author chufangzheng
 */
@Service
@Slf4j
public class ActivityServiceImpl extends ServiceImpl<ActivityDao, ActivityEntity> implements ActivityService  {

    @Autowired
    private ActivityPartiService activityPartiService;

    @Autowired
    private OaLearnClassService oaLearnClassService;
    /**
     * 活动图片URL前缀
     */
    @Value("${activity.url}")
    private String imageUrlPrefix;

    @Autowired
    private OaUserService oaUserService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private AuthService authService;


    @Override
    public IPage<ActivityPageVO> page(Integer pageNum, Integer pageSize, HttpSession session) {

        QueryWrapper<ActivityEntity> qw = new QueryWrapper<>();
        qw.lambda().select(ActivityEntity::getId,
                ActivityEntity::getTitle,
                ActivityEntity::getStartTime,
                ActivityEntity::getEndTime,
                ActivityEntity::getAddress,
                ActivityEntity::getThumbnail)
                .eq(ActivityEntity::getIsPublish, IsPublishTypeEnum.YES.getCode());
        IPage<ActivityEntity> page = new Page<>(pageNum, pageSize);
        page = page(page, qw);
        // 执行任务逻辑
        String openid = authService.getOpenid(session);
        Integer userId = authService.getUserId(session);
        taskService.execTask(userId, openid, OaIntegralRuleEnum.ACTIVITY);

        return page.convert(activityEntity -> {
            ActivityPageVO activityPageVO = BeanUtil.transform(ActivityPageVO.class, activityEntity);
            String startTime = DateUtil.format(new Date( activityEntity.getStartTime() * 1000 ), "yyyy.MM.dd");
            String endTime = DateUtil.format(new Date( activityEntity.getEndTime() * 1000 ), "MM.dd");
            activityPageVO.setStartTime(startTime);
            activityPageVO.setThumbnail(imageUrlPrefix + activityEntity.getThumbnail());
            activityPageVO.setEndTime(endTime);
            activityPageVO.setStatus(ActivityStatusEnum.getStatus(activityEntity.getStartTime(), activityEntity.getEndTime()).getMessage());
            return activityPageVO;
        });
    }

    @Override
    public ActivityInfoVO info(Integer actId, Integer userId) {

        ActivityEntity activityEntity = getById(actId);
        ActivityInfoVO result = BeanUtil.transform(ActivityInfoVO.class, activityEntity);
        String startTime = DateUtil.format(new Date( activityEntity.getStartTime() * 1000 ), DatePattern.CHINESE_DATE_PATTERN);
        String endTime = DateUtil.format(new Date( activityEntity.getEndTime() * 1000 ), DatePattern.CHINESE_DATE_PATTERN);
        result.setStartTime(startTime);
        result.setEndTime(endTime);
        ActivityStatusEnum statusEnums = ActivityStatusEnum.getStatus(activityEntity.getStartTime(), activityEntity.getEndTime());
        result.setStatus(statusEnums.getMessage());
        result.setStatusCode(statusEnums.getCode());

        List<String> images = JSONUtil.toList(activityEntity.getAchieveImage(), String.class);
        images = images.stream().map( image ->  imageUrlPrefix + image ).collect(Collectors.toList());
        result.setAchieveImage(images);
        result.setImages( imageUrlPrefix + activityEntity.getImages() );
        result.setApplyNum(activityPartiService.getApplyNum(activityEntity.getId()));
        result.setIsRegistered(activityPartiService.getIsRegistered(activityEntity.getId(), userId));
        result.setIsCheckin(activityPartiService.getIsCheckin(activityEntity.getId(), userId));
        result.setApplyNum(activityPartiService.getApplyNum(actId));

        return result;
    }

    @Override
    public void registration(Integer actId, Integer userId) {
        // 查询 act 信息
        OaUserEntity user = oaUserService.getById(userId);
        ActivityEntity act = getById(actId);
        Integer type = act.getType();
        checkTypeAndOrg(user, act, type);
        activityPartiService.registration( actId, userId,  user);
    }

    @Override
    public void checkin(ActivityCheckinParam activityCheckinParam, Integer userId) {

        log.info( "打印获取位置信息等参数：" + activityCheckinParam.toString());
        // 查询 act 信息
        OaUserEntity user = oaUserService.getById(userId);
        ActivityEntity act = getById(activityCheckinParam.getId());
        Integer type = act.getType();
        checkTypeAndOrg(user, act, type);
        // 活动时间规则的校验
        if(ActivityTypeEnum.CHECK.getCode().equals(type)){
            // 检查当前时间是否在指定时间范围之内
            Long startTime = act.getStartTime();
            Long endTime = act.getEndTime();
            Long currentSecond =  System.currentTimeMillis()/1000;
            // 活动时间提示
            if( startTime < currentSecond && currentSecond < endTime ){
                // 获取时间
                LocalTime currentTime = LocalTime.now();
                int currentMinute = getMinute(currentTime, currentTime.getMinute());
                // 定义起始时间和结束时间
                LocalTime checkinStartTime = LocalTime.parse(act.getCheckinStartTime());
                LocalTime checkinEndTime = LocalTime.parse(act.getCheckinEndTime());
                // 结束时间
                int startMinute = getMinute(checkinStartTime, checkinStartTime.getMinute());
                int endMinute = getMinute(checkinEndTime, checkinStartTime.getMinute());
                if(startMinute > currentMinute  ){
                    throw new ServiceException("本活动须在" + act.getCheckinStartTime()+ "~" + act.getCheckinEndTime() + "时间段完成打卡！");
                }
                if(currentMinute > endMinute){
                    throw new ServiceException("本活动须在" + act.getCheckinStartTime()+ "~" + act.getCheckinEndTime() + "时间段完成打卡！");
                }
            }else{
                throw new ServiceException("本活动须在" + getDateStr(startTime) + "~" + getDateStr(endTime) + "完成打卡");
            }
        }
        activityPartiService.checkin(activityCheckinParam, userId, act);
    }

    private String getDateStr(Long startTime) {
        Date startDate = DateUtil.date(startTime * 1000);
        String startDateStr = DateUtil.format(startDate, "yyyy-MM-dd");
        return startDateStr;
    }

    /**
     * 获取分钟
     * @param currentTime
     * @param minute
     * @return
     */
    private int getMinute(LocalTime currentTime, int minute) {
        return currentTime.getHour() * 60 + minute;
    }

    /**
     * 检查类型和机构
     * @param user
     * @param act
     * @param type
     */
    private void checkTypeAndOrg(OaUserEntity user, ActivityEntity act, Integer type) {

        if (ActivityTypeEnum.CHECK.getCode().equals(type) == false) {
            throw new ServiceException("当前活动类型仅做展示不需要打卡！");
        }
        // 限制机构
        if (act.getOrgLimit()) {
            if (user.getPath().contains(act.getOrgPath()) == false) {
                OaLearnClassEntity classEntity = oaLearnClassService.getById(act.getPid());
                throw new ServiceException("当前活动需在" + classEntity.getName() + "机构下完成打卡！");
            }
        }
    }


}
